package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.domain.vo.PointsStatisticsVO;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.service.IPointsRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 学习积分记录，每个月底清零 服务实现类
 * </p>
 *
 * @author lcm
 * @since 2023-07-29
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PointsRecordServiceImpl extends ServiceImpl<PointsRecordMapper, PointsRecord> implements IPointsRecordService {
    private final StringRedisTemplate redisTemplate;


    @Override
    public void addPointRecord(Long userId, int writeReplyPoint, PointsRecordType type) {
        int maxPoints = type.getMaxPoints();
        LocalDateTime now = LocalDateTime.now();
        int realPoints=writeReplyPoint;
        //1.判断当前方式有没有积分上限
        if(maxPoints > 0){
            //2.有，则需要判断是否超过上限
            LocalDateTime begin = DateUtils.getDayStartTime(now);
            LocalDateTime end = DateUtils.getDayEndTime(now);
//            int points=queryUserPointByTypeAndDate(userId,type,begin,end);
            //2.1查询今日已得积分
            List<PointsRecord> list = lambdaQuery()
                    .eq(PointsRecord::getUserId, userId)
                    .eq(PointsRecord::getType, type)
                    .between(PointsRecord::getCreateTime, begin, end)
                    .list();
            int points = list.stream().mapToInt(PointsRecord::getPoints).sum();

            //2.2判断是否超过上限
            if(points>=maxPoints){
                //2.3超过，直接结束
                return;
            }
            //2.4没超过，保存积分记录
            if(points+writeReplyPoint>maxPoints){
                realPoints=maxPoints-points;
            }
        }
        //3.没有，直接保存积分记录
        PointsRecord pointsRecord = new PointsRecord();
        pointsRecord.setPoints(realPoints);
        pointsRecord.setUserId(userId);
        pointsRecord.setType(type);
        log.info("保存积分：{}",pointsRecord);
        save(pointsRecord);

        //4.在排行榜里插入记录
        String key= RedisConstants.BOARD_RECORD_KEY_PREFIX+now.format(DateUtils.POINT_BOARD_SUFFIX_FORMATTER);
        redisTemplate.opsForZSet().incrementScore(key,userId.toString(),realPoints);

    }

    @Override
    public List<PointsStatisticsVO> getMyTodayPoints() {
        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.获取当前时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime begin = DateUtils.getDayStartTime(now);
        LocalDateTime end = DateUtils.getDayEndTime(now);
        //3.构建查询条件
        QueryWrapper<PointsRecord> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId)
                .between("create_time", begin, end)
                .groupBy("type")
                .select("type,sum(points) as points");
        //4.查询
        List<PointsRecord> pointsRecords = list(wrapper);
        //健壮性处理
        if(CollUtils.isEmpty(pointsRecords)){
            return CollUtils.emptyList();
        }
        //3.封装VO
        List<PointsStatisticsVO> list = new ArrayList<>();
        for (PointsRecord record : pointsRecords) {
            PointsStatisticsVO vo = new PointsStatisticsVO();
            PointsRecordType type = record.getType();
            vo.setType(type.getDesc());
            vo.setPoints(record.getPoints());
            vo.setMaxPoints(type.getMaxPoints());
            list.add(vo);

        }
        return list;
    }

}
